FCC Basic Algorithm Scripting 基础算法集

前言

本文为 FreeCodeCamp 中前端的十六道基础算法题。


Reverse a String 翻转字符串

★ 具体步骤

  1. 字符串 –> 数组:str.split(“连接符”)

  2. 翻转数组:arr.reverse(),本方法直接改变原数组

  3. 数组 –> 字符串:arr.join(“连接符”)

★ 代码

1
2
3
4
5
6
7
8
9
function reverseString(str) {
var arr = new Array();
arr = str.split("");
arr.reverse();
str = arr.join("");
return str;
}
reverseString("hello"); // olleh

Factorialize a Number 计算一个整数的阶乘

★ 具体步骤

  1. 分情况:if 判断 n=0,n>0

  2. 循环计算:n=0 时,n!=1,n>0 时,循环累乘 n!=1×2×···×n

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function factorialize(num) {
var sum = 1;
if (num == 0) {
sum = 1;
}
else {
for (var i = 1; i <= num; i++) {
sum = sum * i;
}
}
return sum;
}
factorialize(5); // 120

Check for Palindromes 判断回文

★ 要求

回文(palindrome):一个字符串忽略标点符号、大小写和空格,正着读和反着读一模一样,例如 eye。

如果给定的字符串是回文,返回 true,反之,返回 false。

★ 思路

去掉字符串多余的标点符号和空格,然后把字符串转化成小写,翻转之后检查是否与原字符串相等。

★ 具体步骤

  1. 用正则表达式找到字符串多余的标点符号和空格(找出字母和数字即可)

  2. 去除非字母数字符号:str.replace(被替换部分,替换部分)

  3. 将字符串转为小写:str.toLowerCase()

  4. 将字符串翻转:见第一题

  5. 判断翻转后的字符串与原来的是否相同

正则表达式:用来匹配字符串中字符组合的模式。其中 W 表示字母、数字、下划线,因此 [\W_] 就可以表示非字母数字了,也可以用 [^A-Za-z0-9] 表示

★ 代码

1
2
3
4
5
6
7
8
function palindrome(str) {
var re = /[\W_]/g;
var newStr = str.replace(re,"").toLowerCase(); // 纯字母数字的小写形式
var reverseStr = newStr.split("").reverse().join("");
return reverseStr == newStr;
}
palindrome("eye"); // true

Find the Longest Word in a String 找到提供的句子中最长的单词,并计算它的长度

★ 思路

将字符串转为数组,记录下每个数组元素的长度,将长度排序。

★ 具体步骤

  1. 将字符串转为数组:split()

  2. 循环:将每个数组元素的长度保存在新数组中

  3. 排序:将长度数组排序 sort(),得到最大长度值

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function findLongestWord(str) {
var arr = new Array();
var arrLen = new Array();
arr = str.split(" ");
for (var i = 0; i < arr.length; i++){
arrLen[i] = arr[i].length;
}
arrLen.sort(function(a,b) {
return b-a;
});
return arrLen[0];
}
findLongestWord("The quick brown fox jumped over the lazy dog"); // 6

Title Case a Sentence 字符串的单词首字母大写其余小写

★ 思路

先将所有字母统一为小写,再将字符串转化为数组,将每一个数组元素的第一个字符变为大写。

★ 具体步骤

  1. 转小写:将字符串中所有字母转为小写 str.toLowerCase()

  2. 字符串 –> 数组:str.split()

  3. 遍历数组,将每个数组元素第一个字母替换为大写

  • 遍历 arr.map()
  • 替换 arr.replace()
  • 单字符 arr.charAt(index)
  • 大写 toUpperCase()
  1. 数组 –> 字符串:arr.join()

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function titleCase(str) {
str = str.toLowerCase();
var arr = new Array();
arr = str.split(" ");
var newArr = new Array();
newArr = arr.map(toUpper);
function toUpper(element) {
return element.replace(element.charAt(0),element.charAt(0).toUpperCase());
}
str = newArr.join(" ");
return str;
}
titleCase("I'm a little tea pot"); // I'm A Little Tea Pot

Return Largest Numbers in Arrays 将小数组们的最大值串联成新数组

★ 要求

大数组中包含了若干个小数组,分别找到每个小数组中的最大值(数值的最大值),然后把它们串联起来,形成一个新数组。

★ 具体步骤

  1. 先把大数组分为若干小数组

  2. 循环小数组中每一个元素

  3. 找到每个小数组中的最大值

  4. 用新数组存储最大值

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function largestOfFour(arr) {
var newArr = new Array();
for (var i = 0; i < arr.length; i++) {
var max = arr[i][0]; // max 要定义在内层循环外
for (var j = 0; j < arr[i].length; j++) {
if (arr[i][j] >= max) {
max = arr[i][j];
}
}
newArr[i] = max;
}
return newArr;
}
largestOfFour([[4,5,1,3],[13,27,18,26],[32,35,37,39],[1000,10001,857,1]]); // [5,27,39,10001]

Confirm the Ending 检查一个字符串是否以指定的字符串结尾

★ 思路

首先要知道指定字符串 target 的个数,找到待检查字符串中最后几位,判断两者是否相等。

★ 具体步骤

str.substr(beginindex,endindex) 方法:返回字符串从指定位置开始,到指定长度的字符串。

★ 代码

1
2
3
4
5
function confirmEnding(str,target) {
return target == str.substr(str.length-target.length,target.length);
}
confirmEnding("Bastian","n"); // true

Repeat a string repeat a string 重要的事情说3遍

★ 要求

重复一个指定的字符串 num 次,如果 num 是一个负数则返回一个空字符串。

★ 具体步骤

  1. 保留原始字符串:var newStr = str

  2. 循环

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function repeat(str,num) {
var newStr = str;
if (num > 0) {
for (var i = 0; i < num; i++) {
newStr = newStr.concat(str);
}
}
else {
newStr = "";
}
return newStr;
}
repeat("abc",3); // abcabcabcabc

Truncate a string 用瑞兹来截断对面的退路

★ 要求

如果字符串的长度比指定的参数num长,则把多余的部分用…来表示。

切记,插入到字符串尾部的三个点号也会计入字符串的长度。
但是,如果指定的参数num小于或等于3,则添加的三个点号不会计入字符串的长度

★ 思路

最开始要判断 num 是否大于字符串长度。

当 num 小于字符串长度时,分 num 小于等于 3 和大于 3 的情况;

当 num<=3 时,直接在字符串后面加三个点;

当 num> 3时,字符串 + 三个点的长度 = num。

★ 具体步骤

  1. num<=3:str.slice()、str.concat(“…”)

  2. num>3:str.slice()、str.concat(“…”)

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function truncate(str,num) {
var newStr;
if (num < str.length) {
if (num <= 3) {
newStr = str.slice(0,num);
newStr = newStr.concat("...");
}
else {
newStr = str.slice(0,num-3);
newStr = newStr.concat("...");
}
}
else {
newStr = str;
}
return newStr;
}
truncate("A-tisket a-tasket A green and yellow basket","A-tisket a-tasket A green and yellow basket".length+2); // A-tisket a-tasket A green and yellow basket

Chunky Monkey 猴子吃香蕉可是掰成好几段来吃哦

★ 要求

把一个数组 arr 按照指定的数组大小 size 分割成若干个数组块。

★ 思路

将分割出的数组块当作一个个数组元素存在一个新的数组中,要确定分割的个数,才好循环。

★ 具体步骤

设定切割起始位置 begin 与 end,并按照 size 大小累加,将切下的数组块循环 push 进新数组中。

arr.slice(beginindex,endindex),切割时包括 beginindex,不包括 endindex。

注意 arr.push() 返回的是长度值。

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function chunk(arr,size) {
var newArr = new Array();
var begin = 0;
var end = size;
for (var i = 0; i < arr.length/size; i++) {
newArr.push(arr.slice(begin,end));
begin = begin + size;
end = end + size;
}
return newArr;
}
chunk(["a","b","c","d","e"],2); // [["a","b"],["c","d"]["e"]]

Slasher Flick 打不死的小强

★ 要求

返回一个数组被截断 n 个元素后还剩余的元素,截断从索引 0 开始(删除数组前 n 个元素)

★ 具体步骤

1
array.splice(start, deleteCount[, item1[, item2[, ...]]])

start 为开始索引值,deleteCount 为整数,表示要移出的元素个数,item1 表示要添加的元素,若无,则函数只删除元素。函数返回被删除元素数组。

★ 代码

1
2
3
4
5
function slasher(arr,howMany) {
return arr.splice(howMany,arr.length-howMany);
}
slasher([1,2,3],2); // [3]

Mutations 蛤蟆可以吃队友,也可以吃对手

★ 要求

如果数组第一个字符串元素包含了第二个字符串元素的所有字符,忽略顺序和大小写,函数返回 true。

例如:["hello", "hey"] 应该返回 false,因为字符串 "hello" 并不包含字符 "y"
再例如:["Alien", "line"] 应该返回 true,因为 "line" 中所有字符都可以在 "Alien" 找到

★ 思路

首先要将两个字符串统一为小写,再看第二个字符串中的所有元素是不是都能在第一个字符串中找到。

★ 具体步骤

  1. 数组->字符串:个数较少,直接用下标赋值

  2. 字符串转小写:str.toLowerCase()

  3. 第二个字符串 –> 数组:str.split()

  4. 检查第二个字符串中的每个字符是否都能在第一个字符串中找到

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function mutation(arr) {
var str1 = arr[0].toLowerCase();
var str2 = arr[1].toLowerCase();
var arr2 = new Array();
arr2 = str2.split("");
for (var i = 0; i < arr2.length; i++) {
if (str1.indexOf(arr2[i]) == -1) {
return false;
}
else {
continue;
}
}
return true;
}
mutation(["hello","hey"]); // false

Falsy Bouncer 真假美猴王

★ 要求

删除数组中的所有假值。

在JavaScript中,假值有 false、null、0、””、undefined 和 NaN

★ 思路

遍历数组,判断是否为假值,是则删除,否则留下。

★ 具体步骤

  1. 遍历数组:arr.filter()

  2. 判断是否为假值:Boolean(element)。element 为假值返回 false,真值返回 true

★ 代码

1
2
3
4
5
6
7
8
9
function bouncer(arr) {
var newArr = arr.fliter(delFalsy);
function delFalsy(element) {
return Boolean(element);
}
return newArr;
}
bouncer([7,"ate","",false,9]); // [7,"ate",9]

Seek and Destroy 金克斯的迫击炮

★ 要求

实现一个摧毁 destroyer 函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值。

例如:destroyer([1, 2, 3, 1, 2, 3], 2, 3) 应该返回 [1, 1]

★ 思路

遍历数组,将与待摧毁值相同的数组元素删除。

★ 具体步骤

  1. 将待摧毁值存入一个数组中:arguments[index]

  2. 遍历数组:arr.filter()

  3. 判断是否要摧毁:循环+判断

★ 注意

  1. filter 是根据其函数返回值判断是否保留该元素,true 为保留,false 为删除。注意循环的结束与跳过情况

  2. arguments[index] 不要放在内部函数中,这样将取不到外部函数的参数

  3. 循环中最好不要调用函数

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function destroyer() {
var arr = arguments[0];
var a = new Array();
var num = arguments.length;
var j = 0;
for (var i = 1; i < num; i++) {
a[j] = arguments[i]; // 待摧毁数组
j++;
}
var newArr = arr.filter(destroy);
function destroy(element) {
for (var k = 0; k < num-1; k++) {
var res;
if (element == a[k]) {
res = false;
break;
}
else {
res = true;
continue;
}
return res;
}
return newArr;
}
}
destroyer([1,2,3,1,2,3],2,3); // [1,1]

Where do I belong 我身在何处

★ 要求

先给数组排序,然后找到指定的值在数组的位置,最后返回位置对应的索引。

例如:where([1,2,3,4], 1.5) 返回 1
因为 1.5 插入到数组 [1,2,3,4] 后变成 [1,1.5,2,3,4],而 1.5 对应的索引值就是 1

★ 具体步骤

  1. 指定元素放入数组:arr.push()

  2. 数组排序:从小到大 arr.sort()

  3. 找到指定元素的索引:arr.indexOf()

★ 代码

1
2
3
4
5
6
7
8
9
function where(arr,num) {
arr.push(num);
arr.sort(function(a,b) {
return a-b; // 从小到大
});
return arr.indexOf(num);
}
where([40,60],50); // 1

Caesars Cipher 让上帝的归上帝,凯撒的归凯撒(凯撒编码)

★ 要求

写一个 ROT13 函数,实现输入加密字符串,输出解密字符串。注意:所有的字母都是大写,不要转化任何非字母形式的字符(例如:空格,标点符号),遇到这些特殊字符,跳过它们。

ROT13:http://www.baike.com/wiki/ROT13&prd=so_1_doc

ROT13

★ 思路

将 A-M 的 Unicode 值 +13,将 N-Z 的 Unicode 值-13。

★ 具体步骤

  1. 得到字符串中每个字母的 Unicode(UTF16) 值:str.charCodeAt(index) 返回 0~65535 之间的整数

  2. 将 A-M 的 Unicode 值 +13,将 N-Z 的 Unicode 值 -13,其余字符不变

  3. Unicode值 –> 字母:String.fromCharCode(Unicode值)

★ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function rot13(str) {
var arr = new Array();
for (var i = 0; i < str.length; i++) {
var utfNum = str.charCodeAt(i);
if (utfNum >= 65 && utfNum <= 90) {
if (utfNum <= 77) {
utfNum += 13;
}
else {
utfNum -= 13;
}
}
arr[i] = String.fromCharCode(utfNum);
}
str = arr.join("");
return str;
}
rot13("SERR CVMMN!"); // "FREE PIZZA!"
Fork me on GitHub